package com.woniuxy.microsysserver.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.woniuxy.bean.BillBean;
import com.woniuxy.bean.CertificationEntity;
import com.woniuxy.bean.MemberEntity;
import com.woniuxy.bean.ResultBean;
import com.woniuxy.microsysserver.entity.CouponEntity;
import com.woniuxy.microsysserver.entity.MemberCouponEntity;
import com.woniuxy.microsysserver.entity.ResponsEntity;
import com.woniuxy.microsysserver.entity.jwt.AuthResult;
import com.woniuxy.microsysserver.feign.MessageFeign;
import com.woniuxy.microsysserver.feign.WalletFeign;
import com.woniuxy.microsysserver.service.BankcardService;
import com.woniuxy.microsysserver.service.MemberCouponService;
import com.woniuxy.microsysserver.service.MemberService;
import com.woniuxy.microsysserver.uitl.Constant;
import com.woniuxy.microsysserver.uitl.JWTUtil;
import com.woniuxy.microsysserver.uitl.MD5;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.MediaType;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Auther: wuson  <br/>
 * Date: 2021/3/10:15:49  <br/>
 * Description:
 */

@RefreshScope
@ApiOperation("门户端用户管理")
@Slf4j
@RequestMapping(value = "/member", produces = MediaType.APPLICATION_JSON_VALUE)
@RestController
public class MemberController implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {
    @Autowired(required = false)
    private MemberService memberService;
    @Autowired(required = false)
    private BankcardService bankcardService;
    @Autowired(required = false)
    private MemberCouponService memberCouponService;

    @Autowired(required = false)
    private RabbitTemplate rabbitTemplate;
    @Autowired(required = false)
    private MessageFeign messageFeign;
    @Autowired(required = false)
    private WalletFeign walletFeign;
    @Autowired(required = false)
    private ValueOperations valueOperations;
    @Autowired(required = false)
    private HashOperations hashOperations;

//    @Value("${xiangrui.host}")
//    private String host;
//    @Value("${xiangrui.port}")
//    private String port;

    @ApiOperation("获取后端ip和端口")
    @GetMapping(value = "/hostandport", produces = MediaType.APPLICATION_JSON_VALUE)
    public String getHostAndPort () {
        String url=memberCouponService.getHostAndPort();
        return JSONObject.toJSONString(ResultBean.builder().code(200).data(url).build());
    }

    @ApiOperation("修改后端ip和端口")
    @GetMapping(value = "/updateHostAndPort", produces = MediaType.APPLICATION_JSON_VALUE)
    public String updateHostAndPort (String url) {
        int res=memberCouponService.updateHostAndPort(url);
        return JSONObject.toJSONString(ResultBean.builder().code(200).msg("修改成功").build());
    }

    @ApiOperation("门户端用户登录")
    @PostMapping(value = "/login", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResultBean memberLogin (@RequestBody MemberEntity currentMemberEntity) {
        //查询账号
        MemberEntity memberEntity = memberService.selectByAccount(currentMemberEntity.getUsername());
        //验证账号密码
        String token = "";
        if (memberEntity != null && memberEntity.getUsername().equals(currentMemberEntity.getUsername())) {
            if (memberEntity.getPassword().equals(MD5.encrypt(currentMemberEntity.getPassword()))) {
                //认证通过，产生JWT令牌
                Map<String, Object> claims = new HashMap<>();
                claims.put("memberName", memberEntity.getUsername());
                token = JWTUtil.createToken(claims);
                AuthResult authResult = AuthResult.builder().token(token).build();
                memberEntity.setToken(token);
                Date nowTime = new Date();
                hashOperations.put("onlineMember", memberEntity.getUsername(), new SimpleDateFormat("yyyy-MM-dd HH;mm:ss").format(nowTime));
                //查看签到情况
                Date signinTime = memberEntity.getSigninTime();
                //没有上一次签到记录
                if (signinTime == null) {
                    return ResultBean.builder().code(200).msg(Constant.LOGIN_SUCCESSFUL).data(memberEntity).build();
                }
                //有上一次签到记录
                //签到间隔大于一天
                if (nowTime.getTime() - signinTime.getTime() > 1000 * 60 * 60 * 24) {
                    memberEntity.setSignin(0);
                    memberService.signOut(memberEntity.getUsername());
                }
                return ResultBean.builder().code(200).msg(Constant.LOGIN_SUCCESSFUL).data(memberEntity).build();
            }
            //错误密码
            return ResultBean.builder().code(601).msg(Constant.WRONG_PASSWORD).build();
        }
        //未知账号
        return ResultBean.builder().code(602).msg(Constant.INVALID_ACCOUNT_NUMBER).build();
    }

    @ApiOperation("门户端产生手机验证码")
    @PostMapping(value = "/createcode", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResultBean createVerificationCode (@RequestBody MemberEntity memberEntity) {
        log.info("用户名:{}", memberEntity.getUsername());
        //调用手机短信接口
        String res = messageFeign.sendMessage(memberEntity.getUsername());
        return ResultBean.builder().code(200).msg(Constant.VERIFICATION_CODE_SENT).build();
    }


    @ApiOperation("门户端通过手机号登录")
    @PostMapping(value = "/loginbytel", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResultBean memberLoginbytel (@RequestBody MemberEntity currentmemberEntity) {
        //根据账号从redis获取验证码
        String code = (String) valueOperations.get(currentmemberEntity.getUsername() + ":code");
        String token = "";
        if (code != null) {
            if (code.equals(currentmemberEntity.getVerificationCode())) {
                //认证通过，产生JWT令牌
                Map<String, Object> claims = new HashMap<>();
                claims.put("memberName", currentmemberEntity.getUsername());
                token = JWTUtil.createToken(claims);
                AuthResult authResult = AuthResult.builder().token(token).build();
                MemberEntity memberEntity = memberService.selectByAccount(currentmemberEntity.getUsername());
                memberEntity.setToken(token);
                Date nowTime = new Date();
                hashOperations.put("onlineMember", memberEntity.getUsername(), new SimpleDateFormat("yyyy-MM-dd HH;mm:ss").format(nowTime));
                //查看签到情况
                Date signinTime = memberEntity.getSigninTime();
                //没有上一次签到记录
                if (signinTime == null) {
                    return ResultBean.builder().code(200).msg(Constant.LOGIN_SUCCESSFUL).data(memberEntity).build();
                }
                //有上一次签到记录
                //签到间隔大于一天
                if (nowTime.getTime() - signinTime.getTime() > 1000 * 60 * 60 * 24) {
                    memberEntity.setSignin(0);
                    memberService.signOut(memberEntity.getUsername());
                }
                return ResultBean.builder().code(200).msg(Constant.LOGIN_SUCCESSFUL).data(memberEntity).build();
            }
            //验证码错误
            return ResultBean.builder().code(603).msg(Constant.WRONG_VERIFICATION_CODE).build();
        }
        //无效账号
        return ResultBean.builder().code(602).msg(Constant.INVALID_ACCOUNT_NUMBER).build();
    }

    @ApiOperation("门户端注册")
    @PostMapping(value = "/register", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResultBean register (@RequestBody MemberEntity currentmemberEntity) {
        //从redis拿到验证码
        String code = (String) valueOperations.get(currentmemberEntity.getUsername() + ":code");
        //验证码校验
        if (code == null || ! code.equals(currentmemberEntity.getVerificationCode())) {
            return ResultBean.builder().code(604).msg(Constant.WRONG_VERIFICATION_CODE).build();
        }
        //查询是否存在账号
        MemberEntity oldmemberEntity = memberService.selectByAccount(currentmemberEntity.getUsername());
        if (oldmemberEntity != null) {
            return ResultBean.builder().code(614).msg(Constant.ACCOUNT_NUMBER_EXISTS).build();

        }
        //先向数据库中，添加数据
        MemberEntity memberEntity = MemberEntity.builder().username(currentmemberEntity.getUsername()).password(currentmemberEntity.getPassword()).build();
        int state = memberService.register(memberEntity);
//        向RabbitMQ中生产数据
        Map<String, Object> data = new HashMap<>();
        data.put("msg", memberEntity.getUsername() + Constant.REGISTER_SUCCESSFUL);
        data.put("id", UUID.randomUUID().toString());//幂等性ID
//        交换机的名称，路由键，具体的数据
//        rabbitTemplate.convertAndSend("fanoutExchange_member",null,data);
        return ResultBean.builder().code(200).msg(Constant.REGISTER_SUCCESSFUL).build();
    }

    @ApiOperation("门户端账号实名认证")
    @PostMapping(value = "/certification", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResultBean certification (@RequestBody MemberEntity currentmemberEntity) {
        //实名认证接口
        String certification = messageFeign.certification(currentmemberEntity.getIdcardName(), currentmemberEntity.getIdcard());
        //实名认证结果
        CertificationEntity certificationEntity = JSON.parseObject(JSON.parseObject(certification).getString("data"), CertificationEntity.class);
        certificationEntity.setUsername(currentmemberEntity.getUsername());
        //1为认证成功
        if (certificationEntity.getRes() == 1) {
            //实名认证
            int state = memberService.certification(certificationEntity, MD5.encrypt(currentmemberEntity.getPayPassword()));
            return ResultBean.builder().code(200).msg(Constant.REAL_NAME_AUTHENTICATION_SUCCESSFUL).build();
        }
        //其他认证失败
        return ResultBean.builder().code(606).msg(Constant.REAL_NAME_AUTHENTICATION_WRONG).build();
    }

    @ApiOperation("门户端根据账号查用户信息")
    @PostMapping(value = "/info", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResultBean getInfo (@RequestBody MemberEntity currentmemberEntity) {
        log.info("对象{}", currentmemberEntity);
        //用户信息
        MemberEntity memberEntity = memberService.selectByAccount(currentmemberEntity.getUsername());
        return ResultBean.builder().code(200).data(memberEntity).build();
    }

    @ApiOperation("门户端积分兑换余额")
    @PostMapping(value = "/pointsexchange", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResultBean pointsExchange (@RequestBody MemberEntity currentmemberEntity) {
        //积分校验
        if (currentmemberEntity.getIntegral() != 100
                && currentmemberEntity.getIntegral() != 500
                && currentmemberEntity.getIntegral() != 1000) {
            return ResultBean.builder().code(601).msg(Constant.WRONG).build();
        }
        //用户信息
        MemberEntity memberEntity = memberService.selectByAccount(currentmemberEntity.getUsername());
        if (memberEntity.getIntegral() < currentmemberEntity.getIntegral()) {
            return ResultBean.builder().code(600).msg(Constant.INSUFFICIENT_POINTS).build();
        }
        //兑换积分
        int i = memberService.updateByName(MemberEntity.builder().username(memberEntity.getUsername())
                .integral(memberEntity.getIntegral() - currentmemberEntity.getIntegral())
                .balance(memberEntity.getBalance() + currentmemberEntity.getIntegral() / 10).build());
        return ResultBean.builder().code(200).msg(Constant.SUCCESSFUL).build();
    }

    @ApiOperation("门户端通过用户名修改任意可修改资料")
    @PostMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResultBean update (@RequestBody MemberEntity memberEntity) {
        int state = memberService.updateByName(memberEntity);
        return ResultBean.builder().code(200).msg(Constant.MODIFIED_SUCCESSFULLY).build();
    }

    @ApiOperation("门户端通过用户名修改密码")
    @PostMapping(value = "/updatepsw", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResultBean updatepsw (@RequestBody MemberEntity memberEntity) {
        String oldPsw = memberService.selectByAccount(memberEntity.getUsername()).getPassword();
        if (oldPsw.equals(MD5.encrypt(memberEntity.getPassword()))) {
            return ResultBean.builder().code(610).msg(Constant.WRONG).build();
        }
        int state = memberService.updatepsw(memberEntity);
        return ResultBean.builder().code(200).msg(Constant.MODIFIED_SUCCESSFULLY).build();
    }

    @ApiOperation("门户端签到")
    @PostMapping(value = "/signin", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResultBean signIn (@RequestBody MemberEntity currentMemberEntity) {

        MemberEntity memberEntity = memberService.selectByAccount(currentMemberEntity.getUsername());
        if (currentMemberEntity.getSignin() - 1 != memberEntity.getSignin()) {
            return ResultBean.builder().code(600).msg(Constant.WRONG).build();
        }
        int state = memberService.signIn(memberEntity);
        return ResultBean.builder().code(200).msg(Constant.SUCCESSFUL).build();
    }

    @ApiOperation("支付,生成账单")
    @PostMapping(value = "/balancepayment", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResultBean balancePayment (@RequestBody BillBean billBean) {

        //验证支付密码
        String oldPayPassword = memberService.selectByAccount(billBean.getMemberName()).getPayPassword();
        //余额支付
        if (billBean.getIsloan() != 1 && billBean.getPayType().contains(Constant.BALANCE) && oldPayPassword == null) {
            //支付密码为空：未实名
            return ResultBean.builder().code(608).msg(Constant.NO_REAL_NAME).build();
        }
        if (billBean.getIsloan() != 1 && billBean.getPayType().contains(Constant.BALANCE) && ! oldPayPassword.equals(MD5.encrypt(billBean.getPayPassword()))) {
            //支付密码错误
            return ResultBean.builder().code(607).msg(Constant.WRONG_PASSWORD).build();
        }
        //银行卡支付
        if (billBean.getIsloan() != 1 && billBean.getPayType().contains(Constant.BANKCARD)) {
            String bankPsw = bankcardService.selectByid(billBean.getBankCardId()).getPassword();
            if (! billBean.getPayPassword().equals(bankPsw)) {
                //支付密码错误
                return ResultBean.builder().code(607).msg(Constant.WRONG_PASSWORD).build();
            }

        }
        int couponMoney = 0;
        Boolean flag = false;
        //基础支付金额
        Double money = billBean.getModifiedPrice();
        if (billBean.getCouponId() != null && billBean.getCouponId() != 0) {
            //根据couponid查询优惠券id
            MemberCouponEntity memberCouponEntity = memberCouponService.getOneById(billBean.getCouponId());
            //使用优惠券
            CouponEntity couponEntity = memberService.selectCouponById(memberCouponEntity.getCouponId());
            //优惠券校验
            if (couponEntity.getCondition() > money || ! couponEntity.getType().equals(billBean.getProductType()) || couponEntity.getStatus() != 1) {
                return ResultBean.builder().code(610).msg(Constant.COUPON_MISMATCH).build();
            } else {
                money = money - couponEntity.getValue();
                MemberEntity currentMemberEntity = memberService.selectByAccount(billBean.getMemberName());
                if (currentMemberEntity.getBalance() < money) {
                    return ResultBean.builder().code(600).msg(Constant.INSUFFICIENT_BALANCE).build();
                }
                //校验通过，改变优惠券状态为2（已使用）
                int state = memberService.userCoupon(billBean.getCouponId());
                billBean.setCouponName(couponEntity.getType() + "优惠券");
                billBean.setCouponValue(couponEntity.getValue());
                flag = true;
                couponMoney = couponEntity.getValue();
                billBean.setModifiedPrice(money);

            }
        }
        String status = "";
        //从余额扣除相应费用
        if (billBean.getPayType().contains(Constant.BALANCE)) {
            status = memberService.balancePayment(billBean.getMemberName(), money);
        }
        //扣除银行卡余额
        if (billBean.getPayType().contains(Constant.BANKCARD)) {
            status = memberService.balancePaymentByBank(billBean.getMemberName(), money, billBean.getBankCardId());
        }

        if (! status.equals(Constant.SUCCESSFUL)) {
            return ResultBean.builder().code(600).msg(status).data(billBean).build();
        }
        //调用账单接口生成消费账单
        String fakeOrder = walletFeign.createFakeOrder(billBean);
        BillBean billBean1 = JSON.parseObject(JSON.parseObject(fakeOrder).getString("data"), BillBean.class);
        if(flag){
            billBean1.setModifiedPrice(billBean1.getModifiedPrice()+couponMoney);
        }
        return ResultBean.builder().code(200).msg(status).data(billBean1).build();

    }

    @ApiOperation("根据账号和产品类型查询账单信息")
    @PostMapping("selectNewOrder")
    public ResultBean selectNewOrder (@RequestBody BillBean billBean) {
        if (ObjectUtils.isEmpty(billBean)) {
            return ResultBean.ParamError();
        }
        List<BillBean> billBeans = walletFeign.selectNewOrder(billBean);
        if (billBeans == null || billBeans.size() == 0) {
            return ResultBean.builder().code(710).msg("该类型产品暂无交易记录").build();
        } else {
            return ResultBean.builder().code(200).msg("成功").data(billBeans).build();
        }
    }

    @RequestMapping(value = "/send")
    public ResponsEntity sendMsg (String exchage, String routingKey, String msg) {
        //针对当前消息开启确认回调
        rabbitTemplate.setConfirmCallback(this);
        //针对当前消息开启不可达回调
        rabbitTemplate.setReturnCallback(this);
        Map<String, Object> data = new HashMap<>();
        data.put("msg", msg);//传递的消息
        data.put("id", UUID.randomUUID().toString());
        //发送消息
        //设定关联数据ID
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(exchage, routingKey, data, correlationData);
        return ResponsEntity.builder().code(200).msg("发送成功").build();
    }

    /**
     * 异步确认
     *
     * @param correlationData
     *         关联数据
     * @param ack
     *         确认情况
     * @param cause
     *         错误原因
     */
    @Override
    public void confirm (CorrelationData correlationData, boolean ack, String cause) {
        log.info("消息关联数据的ID--{}", correlationData.getId());
        if (ack) {
            log.info("消息关联数据的ID--{}，确认发送成功！", correlationData.getId());
        } else {
            log.info("消息关联数据的ID" + correlationData.getId() + "发送失败，原因是：{}", cause);
        }
    }

    /**
     * 处理消息不可达
     *
     * @param message
     * @param replyCode
     * @param replyText
     * @param exchange
     * @param routingKey
     */
    @Override
    public void returnedMessage (Message message, int replyCode, String replyText, String exchange, String routingKey) {
        try {
            log.info("消息不可达，消息是：{}，状态码是: {},返回内容：{}，交换机是：{}，路由Key是：{}",
                    new String(message.getBody(), "UTF-8"),
                    replyCode, replyText, exchange, routingKey);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
}
